import os
import sys
import ctypes
import requests
from bs4 import BeautifulSoup
import re
import time
import random
from urllib.parse import quote

class BingImageCrawler:
    def __init__(self, save_dir='data', headers=None):
        self.save_dir = save_dir
        self.headers = headers or {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        }
        
    def create_folder(self, folder_name):
        """创建保存图片的文件夹"""
        folder_path = os.path.join(self.save_dir, folder_name)
        os.makedirs(folder_path, exist_ok=True)
        return folder_path
        
    def download_image(self, url, folder_path, index):
        """下载单张图片"""
        try:
            response = requests.get(url, headers=self.headers, timeout=10)
            if response.status_code == 200:
                # 获取图片格式
                content_type = response.headers.get('content-type', '')
                ext = '.jpg' if 'jpeg' in content_type else '.png'
                
                # 生成基础文件名
                base_name = f'image_{index}'
                file_name = f'{base_name}{ext}'
                file_path = os.path.join(folder_path, file_name)
                
                # 检查文件是否存在，如果存在则重命名
                counter = 1
                while os.path.exists(file_path):
                    file_name = f'{base_name}_{counter}{ext}'
                    file_path = os.path.join(folder_path, file_name)
                    counter += 1
                
                # 保存图片
                with open(file_path, 'wb') as f:
                    f.write(response.content)
                print(f"✓ 成功下载第 {index} 张图片: {file_name}")
                return True
        except Exception as e:
            print(f"✗ 第 {index} 张图片下载失败")
        return False
        
    def crawl_images(self, keyword, num_images=100):
        """爬取指定数量的图片"""
        folder_path = self.create_folder(keyword)
        downloaded_count = 0
        page = 1
        
        while downloaded_count < num_images:
            # 构造URL
            encoded_keyword = quote(keyword)
            url = f"https://cn.bing.com/images/search?q={encoded_keyword}&form=HDRSC2&first={page}"
            
            try:
                response = requests.get(url, headers=self.headers)
                soup = BeautifulSoup(response.text, 'html.parser')
                
                # 提取图片URL
                img_pattern = r'murl&quot;:&quot;(.*?)&quot;'
                img_urls = re.findall(img_pattern, response.text)
                
                if not img_urls:
                    print("没有找到更多图片")
                    break
                
                # 下载图片
                for img_url in img_urls:
                    if downloaded_count >= num_images:
                        break
                        
                    if self.download_image(img_url, folder_path, downloaded_count + 1):
                        downloaded_count += 1
                        
                    # 随机延迟，避免被封
                    time.sleep(random.uniform(0.5, 2))
                
                page += 1
                
            except Exception as e:
                print(f"爬取页面失败: {url}")
                print(f"错误信息: {str(e)}")
                break
                
        print(f"\n总共下载了 {downloaded_count} 张图片")
        return downloaded_count

def show_welcome():
    """显示欢迎界面和声明信息"""
    welcome_text = """
    ====================================================
                必应图片爬虫工具 v1.0
    ====================================================
    
    版权声明：
    Copyright © 2024 陈祖豪 QQ:3469807212 All Rights Reserved
    本程序仅供学习和研究使用
    
    免责声明：
    1. 本程序仅供个人学习研究使用，禁止用于商业用途
    2. 使用本程序产生的任何后果由用户自行承担
    3. 请遵守相关法律法规，不得爬取违法违规内容
    4. 请合理使用，避免对目标网站造成过大压力
    
    使用步骤：
    1. 输入要搜索的关键词
    2. 输入要下载的图片数量
    3. 程序会自动在data/关键词目录下保存图片
    
    ====================================================
    """
    print(welcome_text)

def set_windows_compatibility():
    if sys.platform == 'win32':
        # 启用高 DPI 支持
        try:
            ctypes.windll.shcore.SetProcessDpiAwareness(1)
        except:
            pass
        
        # 设置应用程序兼容性标志
        try:
            ctypes.windll.kernel32.SetProcessDPIAware()
        except:
            pass

def main():
    # 设置 Windows 兼容性
    set_windows_compatibility()
    
    # 显示欢迎界面
    show_welcome()
    
    # 用户确认
    confirm = input("请确认您已阅读并同意上述声明（Y/N）: ")
    if confirm.lower() != 'y':
        print("您没有同意声明，程序退出...")
        return
        
    # 创建爬虫实例
    crawler = BingImageCrawler()
    
    # 设置关键词和数量
    while True:
        try:
            keyword = input("\n请输入要搜索的关键词: ")
            if not keyword.strip():
                print("关键词不能为空，请重新输入！")
                continue
                
            num_images = input("请输入要下载的图片数量: ")
            num_images = int(num_images)
            if num_images <= 0:
                print("图片数量必须大于0，请重新输入！")
                continue
            break
        except ValueError:
            print("请输入有效的数字！")
    
    # 开始爬取
    print(f"\n开始爬取 '{keyword}' 的图片...")
    crawler.crawl_images(keyword, num_images)
    
    # 程序结束提示
    input("\n按回车键退出程序...")

if __name__ == "__main__":
    main() 